/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

#include "runtime/include/runtime.h"
#include "plugins/ecmascript/runtime/ecma_vm.h"

namespace ark::test {
class EcmaEmptyClassCheck : public testing::Test {
public:
    std::string GetJSAbcFile()
    {
        auto execPath = ark::os::file::File::GetExecutablePath();
        return execPath.Value() +
               "/../plugins/ecmascript/tests/runtime/common/ecma_empty_class_check/ecma_empty_class_check.abc";
    }
};

static void CheckNames(const panda_file::File &pf)
{
    Span<const uint32_t> classIndexes = pf.GetClasses();

    for (const uint32_t index : classIndexes) {
        panda_file::File::EntityId classId(index);
        if (pf.IsExternal(classId)) {
            continue;
        }
        panda_file::ClassDataAccessor cda(pf, classId);
        cda.EnumerateMethods([&pf](panda_file::MethodDataAccessor &mda) {
            auto sdMname = mda.GetName();
            std::string mname(reinterpret_cast<const char *>(sdMname.data), sdMname.utf16Length);
            ASSERT(!mname.empty());

            auto sdCname = pf.GetStringData(mda.GetClassId());
            std::string cname(reinterpret_cast<const char *>(sdCname.data), sdCname.utf16Length);
            ASSERT(!cname.empty());
        });
    }
}

TEST_F(EcmaEmptyClassCheck, TestJSABC)
{
    RuntimeOptions options;
    options.SetLoadRuntimes({"ecmascript"});
    options.SetBootPandaFiles({});
    // NOLINTNEXTLINE(readability-magic-numbers)
    options.SetHeapSizeLimit(50_MB);
    options.SetGcType("epsilon");

    ASSERT_TRUE(Runtime::Create(options));

    auto *ecmaVm = reinterpret_cast<ark::ecmascript::EcmaVM *>(Runtime::GetCurrent()->GetPandaVM());

    ASSERT_TRUE(ecmaVm);

    std::unique_ptr<const panda_file::File> pf =
        panda_file::OpenPandaFile(GetJSAbcFile(), "", panda_file::File::OpenMode::READ_WRITE);

    ASSERT_TRUE(pf);
    CheckNames(*pf);

    ASSERT_TRUE(ecmaVm->ExecuteFromBuffer(pf->GetBase(), pf->GetPtr().GetSize(), "_GLOBAL::func_main_0", {}));

    Runtime::Destroy();
}
}  // namespace ark::test
